package com.dcivision.framework.taglib.calendar;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;

public class CalendarTag extends BodyTagSupport {

  public static final String REVISION = "$Revision: 1.4 $";

  private static final String DAY = "$d";
  private static final String MONTH = "$m";
  private static final String YEAR = "$y";
  private int month;
  private int year;
  private Locale locale;
  private boolean header;
  private String headerStyle;
  private String headerClass;
  private String defStyle;
  private String defClass;
  private String nextMonth;
  private String prevMonth;
  private HttpServletResponse res;
  private CascadingStyleSheet titles[];
  private CascadingStyleSheet days[];

  public CalendarTag() {
    headerStyle = null;
    headerClass = null;
    defStyle = null;
    defClass = null;
    nextMonth = null;
    prevMonth = null;
    GregorianCalendar gregoriancalendar = new GregorianCalendar();
    locale = Locale.US;
    month = gregoriancalendar.get(2) + 1;
    year = gregoriancalendar.get(1);
    header = false;
  }

  public int doAfterBody() throws JspException {
    StringBuffer stringbuffer = new StringBuffer("");
    res = (HttpServletResponse)super.pageContext.getResponse();
    if (month <= 0 || month > 12) {
      throw new JspException("Invalid value for month:" + month);
    }
    if (year <= 0) {
      throw new JspException("Invalid value for year:" + year);
    }
    stringbuffer.append("<table cellspacing=0 cellpadding=0 border=0 width=\"100%\">\n");
    if (header) {
      writeHeader(stringbuffer);
    }
    writeBody(stringbuffer);
    stringbuffer.append("</table>\n");
    try {
      JspWriter jspwriter = getPreviousOut();
      jspwriter.print(stringbuffer.toString());
    }
    catch (Exception exception) {
      throw new JspException("Could not save body " + exception.toString());
    }
    return 0;
  }

  public int doStartTag() throws JspException {
    titles = new CascadingStyleSheet[7];
    for (int i = 1; i <= 7; i++) {
      titles[i - 1] = new CascadingStyleSheet();
    }

    days = new CascadingStyleSheet[31];
    for (int j = 1; j <= 31; j++) {
      days[j - 1] = new CascadingStyleSheet();
    }

    return 2;
  }

  private int getDay(Calendar calendar) {
    if (locale.equals(Locale.US)) {
      return calendar.get(7) - 1;
    } else {
      return (calendar.get(7) + 5) % 7;
    }
  }

  public String getDefClass() {
    return defClass;
  }

  public String getDefStyle() {
    return defStyle;
  }

  public boolean getHeader() {
    return header;
  }

  public String getHeaderClass() {
    return headerClass;
  }

  public String getHeaderStyle() {
    return headerStyle;
  }

  public Locale getLocale() {
    return locale;
  }

  public int getMonth() {
    return month;
  }

  public String getNextMonth() {
    return nextMonth;
  }

  public String getPrevMonth() {
    return prevMonth;
  }

  public int getYear() {
    return year;
  }

  private String prepareURL(String s, int i) {
    String s1 = replace(s, "$d", i);
    s1 = replace(s1, "$m", month);
    s1 = replace(s1, "$y", year);
    return res.encodeURL(s1);
  }

  public void release() {
    GregorianCalendar gregoriancalendar = new GregorianCalendar();
    headerStyle = null;
    headerClass = null;
    defStyle = null;
    defClass = null;
    nextMonth = null;
    prevMonth = null;
    days = null;
    titles = null;
    locale = Locale.US;
    month = gregoriancalendar.get(2) + 1;
    year = gregoriancalendar.get(1);
    header = false;
  }

  private String replace(String s, String s1, int i) {
    int j = s.indexOf(s1);
    if (j < 0) {
      return s;
    }
    if (j == 0) {
      return i + replace(s.substring(j + s1.length()), s1, i);
    } else {
      return s.substring(0, j) + i + replace(s.substring(j + s1.length()), s1, i);
    }
  }

  public void setDateClass(int i, String s) {
    days[i].setClassName(s);
  }

  public void setDateField(int i, String s) {
    days[i].setField(s);
  }

  public void setDateLink(int i, String s) {
    days[i].setLink(s);
  }

  public void setDateStyle(int i, String s) {
    days[i].setStyle(s);
  }

  public void setDateTarget(int i, String s) {
    days[i].setTarget(s);
  }

  public void setDefClass(String s) {
    defClass = s;
  }

  public void setDefStyle(String s) {
    defStyle = s;
  }

  public void setHeader(boolean flag) {
    header = flag;
  }

  public void setHeaderClass(String s) {
    headerClass = s;
  }

  public void setHeaderStyle(String s) {
    headerStyle = s;
  }

  public void setLinkClass(int i, String s) {
    days[i].setLinkClass(s);
  }

  public void setLinkStyle(int i, String s) {
    days[i].setLinkStyle(s);
  }

  public void setLocale(Locale locale1) {
    locale = locale1;
  }

  public void setMonth(int i) {
    month = i;
  }

  public void setNextMonth(String s) {
    nextMonth = s;
  }

  public void setPrevMonth(String s) {
    prevMonth = s;
  }

  public void setTitleClass(int i, String s) {
    titles[i].setClassName(s);
  }

  public void setTitleStyle(int i, String s) {
    titles[i].setStyle(s);
  }

  public void setYear(int i) {
    year = i;
  }

  private String stringDate(int i) {
    if (locale.equals(Locale.US)) {
      return twoDigits(month) + "/" + twoDigits(i) + "/" + year;
    } else {
      return twoDigits(i) + "/" + twoDigits(month) + "/" + year;
    }
  }

  private String twoDigits(int i) {
    String s = String.valueOf(i);
    if (s.length() == 2) {
      return s;
    } else {
      return "0" + s;
    }
  }

  private void writeBody(StringBuffer stringbuffer) {
    writeTitle(stringbuffer);
    writeDates(stringbuffer);
  }

  private void writeDates(StringBuffer stringbuffer) {
    GregorianCalendar gregoriancalendar = new GregorianCalendar(year, month - 1, 1);
    int j1 = month - 1;
    int i = 0;
    int l = 0;
    int i1 = 0;
    if (getDay(gregoriancalendar) > 0) {
      stringbuffer.append("<tr>");
      for (; i < getDay(gregoriancalendar); i++) {
        stringbuffer.append("<td align=right");
        if (defClass != null) {
          stringbuffer.append(" class=\"" + defClass + "\"");
        } else
        if (defStyle != null) {
          stringbuffer.append(" style=\"" + defStyle + "\"");
        }
        stringbuffer.append(">&nbsp;</td>\n");
        l++;
      }

    }
    for (; gregoriancalendar.get(2) == j1; gregoriancalendar.add(5, 1)) {
      if (i1 >= days.length) {
        break;
      }
      int j = gregoriancalendar.get(5);
      int k = (i + j) % 7;
      if (k == 1) {
        stringbuffer.append("<tr>\n");
        l = 0;
      }
      stringbuffer.append("<td align=right");
      if (days[i1].getClassName() != null) {
        stringbuffer.append(" class=\"" + days[i1].getClassName() + "\"");
      } else
      if (days[i1].getStyle() != null) {
        stringbuffer.append(" style=\"" + days[i1].getStyle() + "\"");
      }
      l++;
      stringbuffer.append(">");
      stringbuffer.append("&nbsp;");
      if (days[i1].getField() != null) {
        stringbuffer.append("<a");
        if (days[i1].getLinkClass() != null) {
          stringbuffer.append(" class=\"" + days[i1].getLinkClass() + "\"");
        } else
        if (days[i1].getLinkStyle() != null) {
          stringbuffer.append(" style=\"" + days[i1].getLinkStyle() + "\"");
        }
        stringbuffer.append(" href=\"javascript:opener.document." + days[i1].getField() + ".value='");
        stringbuffer.append(stringDate(j));
        stringbuffer.append("';window.close();\">");
        stringbuffer.append(String.valueOf(j));
        stringbuffer.append("</a>");
      } else
      if (days[i1].getLink() != null) {
        stringbuffer.append("<a");
        if (days[i1].getLinkClass() != null) {
          stringbuffer.append(" class=\"" + days[i1].getLinkClass() + "\"");
        } else
        if (days[i1].getLinkStyle() != null) {
          stringbuffer.append(" style=\"" + days[i1].getLinkStyle() + "\"");
        }
        stringbuffer.append(" href=\"" + prepareURL(days[i1].getLink(), j) + "\"");
        if (days[i1].getTarget() != null) {
          stringbuffer.append(" target=\"" + days[i1].getTarget() + "\"");
        }
        stringbuffer.append(">" + j);
        stringbuffer.append("</a>");
      } else {
        stringbuffer.append(String.valueOf(j));
      }
      i1++;
      stringbuffer.append("&nbsp;");
      stringbuffer.append("</td>\n");
      if (k == 0) {
        stringbuffer.append("</tr>\n");
      }
    }

    if (l < 7) {
      for (; l < 7; l++) {
        stringbuffer.append("<td align=right");
        if (defClass != null) {
          stringbuffer.append(" class=\"" + defClass + "\"");
        } else
        if (defStyle != null) {
          stringbuffer.append(" style=\"" + defStyle + "\"");
        }
        stringbuffer.append(">&nbsp;</td>\n");
      }

      stringbuffer.append("</tr>\n");
    }
  }

  private void writeHeader(StringBuffer stringbuffer) {
    GregorianCalendar gregoriancalendar = new GregorianCalendar(year, month - 1, 1);
    SimpleDateFormat simpledateformat = new SimpleDateFormat("MMM", locale);
    boolean flag = false;
    stringbuffer.append("<tr><td");
    if (headerClass != null) {
      stringbuffer.append(" class=\"" + headerClass + "\"");
    } else
    if (headerStyle != null) {
      stringbuffer.append(" style=\"" + headerStyle + "\"");
    }
    stringbuffer.append(">");
    if (prevMonth != null) {
      stringbuffer.append("<a");
      if (headerClass != null) {
        stringbuffer.append(" class=\"" + headerClass + "\"");
      } else
      if (headerStyle != null) {
        stringbuffer.append(" style=\"" + headerStyle + "\"");
      }
      stringbuffer.append(" href=\"" + prepareURL(prevMonth, 1) + "\">&lt;&lt;</a>");
    } else {
      stringbuffer.append("&nbsp;");
    }
    stringbuffer.append("</td>");
    stringbuffer.append("<td colspan=5 align=center");
    if (headerClass != null) {
      stringbuffer.append(" class=\"" + headerClass + "\"");
    } else
    if (headerStyle != null) {
      stringbuffer.append(" style=\"" + headerStyle + "\"");
    } else {
      flag = true;
    }
    stringbuffer.append(">");
    if (flag) {
      stringbuffer.append("<b>");
    }
    stringbuffer.append(simpledateformat.format(gregoriancalendar.getTime()));
    stringbuffer.append(" ");
    stringbuffer.append(year);
    if (flag) {
      stringbuffer.append("</b>");
    }
    stringbuffer.append("</td>");
    stringbuffer.append("<td");
    if (headerClass != null) {
      stringbuffer.append(" class=\"" + headerClass + "\"");
    } else
    if (headerStyle != null) {
      stringbuffer.append(" style=\"" + headerStyle + "\"");
    }
    stringbuffer.append(">");
    if (nextMonth != null) {
      stringbuffer.append("<a");
      if (headerClass != null) {
        stringbuffer.append(" class=\"" + headerClass + "\"");
      } else
      if (headerStyle != null) {
        stringbuffer.append(" style=\"" + headerStyle + "\"");
      }
      stringbuffer.append(" href=\"" + prepareURL(nextMonth, 1) + "\">&gt;&gt;</a>");
    } else {
      stringbuffer.append("&nbsp;");
    }
    stringbuffer.append("</td>");
    stringbuffer.append("</tr>\n");
    stringbuffer.append("<tr><td colspan=7");
    if (headerClass != null) {
      stringbuffer.append(" class=\"" + headerClass + "\"");
    } else
    if (headerStyle != null) {
      stringbuffer.append(" style=\"" + headerStyle + "\"");
    }
    stringbuffer.append(">&nbsp;</td></tr>\n");
  }

  private void writeTitle(StringBuffer stringbuffer) {
    GregorianCalendar gregoriancalendar = new GregorianCalendar(2001, 0, 14);
    SimpleDateFormat simpledateformat = new SimpleDateFormat("EEE", locale);
    boolean flag = false;
    stringbuffer.append("<tr>");
    if (locale.equals(Locale.US)) {
      for (int i = 0; i < 7; i++) {
        boolean flag1 = false;
        stringbuffer.append("<td align=right");
        if (titles[i].getClassName() != null) {
          stringbuffer.append(" class=\"" + titles[i].getClassName() + "\"");
        } else
        if (titles[i].getStyle() != null) {
          stringbuffer.append(" style=\"" + titles[i].getStyle() + "\"");
        } else {
          flag1 = true;
        }
        stringbuffer.append(">");
        if (flag1) {
          stringbuffer.append("<b>");
        }
        stringbuffer.append("&nbsp;");
        stringbuffer.append(simpledateformat.format(gregoriancalendar.getTime()));
        stringbuffer.append("&nbsp;");
        if (flag1) {
          stringbuffer.append("</b>");
        }
        stringbuffer.append("</td>");
        gregoriancalendar.add(5, 1);
      }

    } else {
      for (int j = 0; j < 7; j++) {
        gregoriancalendar.add(5, 1);
        boolean flag2 = false;
        stringbuffer.append("<td align=right");
        if (titles[j].getClassName() != null) {
          stringbuffer.append(" class=\"" + titles[j].getClassName() + "\"");
        } else
        if (titles[j].getStyle() != null) {
          stringbuffer.append(" style=\"" + titles[j].getStyle() + "\"");
        } else {
          flag2 = true;
        }
        stringbuffer.append(">");
        if (flag2) {
          stringbuffer.append("<b>");
        }
        stringbuffer.append("&nbsp;");
        stringbuffer.append(simpledateformat.format(gregoriancalendar.getTime()));
        stringbuffer.append("&nbsp;");
        if (flag2) {
          stringbuffer.append("</b>");
        }
        stringbuffer.append("</td>");
      }

    }
    stringbuffer.append("</tr>\n");
  }

}

